package de.staxx6.bomber;

import java.util.ArrayList;

import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;

import de.staxx6.bomber.box.BombBox;
import de.staxx6.bomber.box.BoxBomber;
import de.staxx6.bomber.box.BrickBox;
import de.staxx6.bomber.box.ExplosionBox;
import de.staxx6.bomber.box.WallBox;

public class Field {
	
	private final int size;
	private Node fieldNode = new Node("Field Node");
	private Node groundNode = new Node("Ground Node");
	public ArrayList<BoxBomber> boxList;
	
	public Field(final int newSize) {
		if((newSize % 2) == 1 && newSize > 4) {
			this.size = newSize;
		} else {
			this.size = 17;
			GameState.FIELDSIZE = 17;
			System.out.println("WARNING: No valid field size! Only odd numbers and above 4!\n" +
							   "         New size: 17");
		}
		boxList = new ArrayList<BoxBomber>();
		createField();
		System.out.println("Field created with: " + Stats.TOTALBOXES + " total boxes.");
		System.out.println("Field created with: " + Stats.BRICKBOXES + " brick boxes.");
		System.out.println("Field created with: " + Stats.WALLBOXES + " wall boxes.");
	}
	
	private void createField() {
		/* Ground */
		Box box_ground = new Box(new Vector3f(size / 2 + 1f, size / 2 + 1f, 0), size / 2 + 0.5f, size / 2 + 0.5f, 1);
		Geometry ground = new Geometry("Ground", box_ground);
		Material mat_ground = new Material(GameState.ASSETMANAGER, "Common/MatDefs/Misc/Unshaded.j3md");
		//mat_ground.setTexture("ColorMap", assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg"));
		mat_ground.setColor("Color", ColorRGBA.DarkGray);
		ground.setMaterial(mat_ground);
		groundNode.attachChild(ground);
		
		/* Boxes */
		for(int y = 1; y < size + 1; y++) {
			for(int x = 1; x < size + 1; x++) {
				if(isWallBox(x, y)) {
					boxList.add(new WallBox(x, y));
				}
			}
		}
		/* Get the wall nodes */
		for(int i = 0; i < boxList.size(); i++) {
			fieldNode.attachChild(boxList.get(i).getNode());
		}
	}
	
	public void createRandomBricks() {
		for(int y = 1; y < size + 1; y++) {
			for(int x = 1; x < size + 1; x++) {
				if(isPlaceForOtherBrick(x, y)) {
					if(isRandomBrick()) {
						boxList.add(new BrickBox(x, y, fieldNode));
					}
				}
			}
		}
	}
	
	public void update(float delta) {
		for(int i = 0; i < boxList.size(); i++) {
			boxList.get(i).update(delta);
			if(boxList.get(i) instanceof ExplosionBox) {
				if(((ExplosionBox) boxList.get(i)).isRemoved()) {
					boxList.remove(i);
				}
			}
		}
	}
	
	public boolean isPlaceForOtherBrick(final int fieldX, final int fieldY) {
		boolean isOtherBoxFree = true;
		
		for(int i = 0; i < boxList.size(); i++) {
			Vector2f boxPos = boxList.get(i).getBoxPosition();
			if(boxPos.x == fieldX && boxPos.y == fieldY) {
				isOtherBoxFree = false;
			}
		}
		if(isPlayerBox(fieldX, fieldY)) {
			isOtherBoxFree = false;
		}
		
		return isOtherBoxFree;
	}
	
	public void bombExplode(final int fieldX, final int fieldY) {
		for(int i = 0; i < boxList.size(); i++) {
			Vector2f boxPos = boxList.get(i).getBoxPosition();
			if(boxPos.x == fieldX && boxPos.y == fieldY) {
				if(boxList.get(i).getType().equals("BombBox")) {
					if(!((BombBox) boxList.get(i)).isInExplosing()) {
						((BombBox) boxList.get(i)).explode();
					}
				}
			}
		}
	}
	
	public void destroyBrick(final int fieldX, final int fieldY) {
		for(int i = 0; i < boxList.size(); i++) {
			Vector2f boxPos = boxList.get(i).getBoxPosition();
			if(boxPos.x == fieldX && boxPos.y == fieldY) {
				if(boxList.get(i).getType().equals("BrickBox")) {
					GameState.BULLETAPPSTATE.getPhysicsSpace().remove(((BrickBox)boxList.get(i)).getPhysic());
					boxList.get(i).getNode().removeFromParent();
					boxList.remove(i);
					
					// neue box art erstellen (collosion) ansonsten stirbt der Spieler sofort beim
					// rein laufen!
					boxList.add(new ExplosionBox(boxPos.x, boxPos.y, fieldNode, true));
				}
			}
		}
	}
	
	public boolean isExplosionBox(final int fieldX, final int fieldY) {
		boolean isExplosionBox = false;
		
		for(int i = 0; i < boxList.size(); i++) {
			Vector2f boxPos = boxList.get(i).getBoxPosition();
				if(boxPos.x == fieldX && boxPos.y == fieldY) {
					if(boxList.get(i).getType().equals("ExplosionBox")) {
						isExplosionBox = true;
					}
				}
		}
		return isExplosionBox;
	}
	
	public boolean isPlace(final int fieldX, final int fieldY) {
		boolean isPlace = true;
		
		for(int i = 0; i < boxList.size(); i++) {
			Vector2f boxPos = boxList.get(i).getBoxPosition();
			if(boxPos.x == fieldX && boxPos.y == fieldY) {
				isPlace = false;
			}
		}
		return isPlace;
	}
	
	private boolean isWallBox(final int fieldX, final int fieldY) {
		boolean isWall = false;
		int fieldSize = GameState.FIELDSIZE; 
		// Outline
		if(fieldX == 1 || fieldX == fieldSize) {
			isWall = true;
		}
		if(fieldY == 1 || fieldY == fieldSize) {
			isWall = true;
		}
		// Area walls
		for(int i = 0; i < fieldSize - 2; i++) {
			//No first inline
			if(fieldX != 1 && fieldX != fieldSize
					&& fieldY != 1 && fieldY != fieldSize) {
				// Inner area
				if(1 == (fieldY % 2) && 1 == (fieldX % 2)) {
					isWall = true;
				}
			}
		}
		return isWall;
	}
	
	private boolean isPlayerBox(final int fieldX, final int fieldY) {
		boolean isPlayerBox = false;

		int fieldSize = GameState.FIELDSIZE;
		//Player One
		if(fieldX == 2 && fieldY == (fieldSize - 1) 
			|| fieldX == 3 && fieldY == (fieldSize - 1) 
				|| fieldX == 2 && fieldY == (fieldSize - 2)) {
			
			isPlayerBox = true;
		}

		//Player Two
		if(fieldX == (fieldSize - 1) && fieldY == 3 
			|| fieldX == (fieldSize - 2) && fieldY == 2 
				|| fieldX == (fieldSize - 1) && fieldY == 2) {
			
			isPlayerBox = true;
		}
		// Player Three
		if(GameState.PLAYERNUMBER > 2) {
			if(fieldX == (fieldSize - 1) && fieldY == (fieldSize - 1) 
				|| fieldX == (fieldSize - 2) && fieldY == (fieldSize - 1) 
					|| fieldX == (fieldSize - 1) && fieldY == (fieldSize - 2)) {
				
				isPlayerBox = true;
			}
		}
		// Player Four
		if(GameState.PLAYERNUMBER > 3) {
			if(fieldX == 2 && fieldY == 2|| fieldX == 3 && fieldY == 2 || fieldX == 2 && fieldY == 3) {
				isPlayerBox = true;
			}
		}
		return isPlayerBox;
	}
	
	private boolean isRandomBrick() {
		boolean isRandomBrick = false;
		
		// Random number 0.01 - 1  
		float rand = (float) Math.random();
		
		if(rand < GameState.FIELDBRICKDENSITY) {
			isRandomBrick = true;
		}
		return isRandomBrick;
	}
	
	public Node getNode() {
		return fieldNode;
	}
	
	public Node getNodeGround() {
		return groundNode;
	}
}
